package com.system.boot.setting.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.system.api.SuperInterface;
import com.system.api.setting.entity.po.SysDict;
import com.system.api.setting.entity.po.SysDictItem;
import com.system.boot.setting.mapper.DictItemMapper;
import com.system.boot.setting.mapper.DictMapper;
import com.system.boot.setting.service.DictService;
import com.system.common.enums.FactoryEnum;
import com.system.common.factory.CacheFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yang.common.core.exception.BaseException;
import org.yang.common.i18n.constant.I18nMessageConstant;
import org.yang.database.orm.entity.BaseModel;
import org.yang.database.orm.entity.BaseQuery;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static com.system.common.constant.MessageConstant.CATALOGUE_CODE_EMPTY;


/**
 * @author: lslands
 * @version: 1.0
 * @create: 2024/5/18
 * @description:
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DictServiceImpl extends ServiceImpl<DictMapper, SysDict> implements DictService, SuperInterface<SysDict> {

  private final CacheFactory cacheFactory;
  private final DictItemMapper dictItemMapper;


  @Override
  public void isExists(String code) throws BaseException {
    boolean existsByCode = baseMapper.getExistsByCode(code);
    if (existsByCode) {
      throw new BaseException(BaseException.REPEAT, code);
    }
  }

  @Override
  public int handInsert(SysDict record) throws BaseException {
    String code =
        Optional.ofNullable(record.getCode())
            .orElseThrow(() -> new BaseException(CATALOGUE_CODE_EMPTY));
    this.isExists(code);
    record.setCode(code.toLowerCase());
    int result = baseMapper.insert(record);
    this.resetCache(result > 0);
    return result;
  }

  @Override
  public int handUpdateById(SysDict record) throws BaseException {
    SysDict oldResult =
        Optional.ofNullable(baseMapper.selectById(record.getId()))
            .orElseThrow(
                () -> new BaseException(BaseException.NULL));
    if (!Objects.equals(record, oldResult)) {
      String code = Optional.ofNullable(record.getCode())
              .orElseThrow(() -> new BaseException(CATALOGUE_CODE_EMPTY));
      // 不区分大小写 equalsIgnoreCase
      if (!code.equalsIgnoreCase(oldResult.getCode())) {
        this.isExists(record.getCode());
        record.setCode(record.getCode().toLowerCase());
      }
      int result = baseMapper.updateById(record);
      this.resetCache(result > 0);
      return result;
    }
    return 1;
  }

  @Override
  public int handEnabledById(Long id, Integer enabled, Integer revision) throws BaseException {
    SysDict oldResult = Optional.ofNullable(baseMapper.selectById(id))
            .orElseThrow(()-> new BaseException(BaseException.NULL));
    if(null==enabled){
      throw new BaseException(I18nMessageConstant.VALIDATION_STATUS_EMPTY);
    }
    if(enabled.equals(oldResult.getEnabled())){
      return 1;
    }
    int result = baseMapper.updateById(new SysDict(id, enabled, revision));
    this.resetCache(result > 0);
    return result;
  }

  @Override
  public Page<SysDict> getPage(BaseQuery query, SysDict record) throws BaseException {
    Page<SysDict> page = new Page<>(query.getCurrent(), query.getSize());
    LambdaQueryWrapper<SysDict> wrapper = new LambdaQueryWrapper<SysDict>()
            .like(StringUtils.isNoneBlank(record.getName()), SysDict::getName, record.getName())
            .eq(record.getEnabled() != null,SysDict::getEnabled,record.getEnabled())
            .orderByDesc(BaseModel::getId);
    return baseMapper.selectPage(page, wrapper);
  }


  @Override
  @Transactional(rollbackFor = RuntimeException.class)
  public int deleteOne(Long id) throws BaseException {
    int result;
    SysDict item = Optional.ofNullable(baseMapper.selectById(id))
            .orElseThrow(()-> new BaseException(BaseException.NULL));
    result = baseMapper.deleteById(id);
    if(null!=item){
      result =dictItemMapper.delete(new LambdaUpdateWrapper<SysDictItem>()
              .eq(SysDictItem::getDictCode, item.getCode()));
    }
    this.resetCache(result>0);
    return result;
  }

  @Override
  public int deleteBatch(Boolean delete, List<Long> ids) throws BaseException {
    int result =0;
    List<SysDict> itemList = baseMapper.selectBatchIds(ids);
    if(!itemList.isEmpty()){
      if(delete){
        result= baseMapper.deleteBatch(ids);
      }else{
        List<SysDictItem> dictItemList =itemList.stream().map(x->
                SysDictItem.builder().dictCode(x.getCode()).build()).toList();
        dictItemMapper.deleteBatchIds(dictItemList);
        result=baseMapper.deleteBatchIds(ids);
      }
      this.resetCache(result > 0);
    }
    return result;
  }


  @Override
  public void resetCache(boolean flag) {
    if (flag) {
      try {
        // 工厂方法
        cacheFactory.implementCacheProcessor(FactoryEnum.DICT.getType()).resetCache();
      } catch (BaseException e) {
        log.error("刷新字典缓存异常:{}", e.getMessage());
      }
    }
  }
}
